home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / MouseModule / HIDEmulation.c next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  11.6 KB  |  366 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        HIDEmulation.c
  3.  
  4.     Contains:    HID Emulation glue code between the ADB SHIM and the USB Mouse HID Module
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <CursorDevices.h>
  16. #include <USB.h>
  17. #include <MixedMode.h>
  18.  
  19. #ifndef LMGetJADBProc
  20. #define LMGetJADBProc() (*((volatile UniversalProcPtr *)0x06B8))
  21. #endif
  22.  
  23. #ifndef LMSetJADBProc
  24. #define LMSetJADBProc(value) ((*(UniversalProcPtr *)0x06B8) = (value))
  25. #endif
  26.  
  27.  
  28. #include "MouseModule.h"
  29.  
  30. enum
  31.     {
  32.     uppJADBProcProcInfo = kRegisterBased
  33.         | RESULT_SIZE(SIZE_CODE(sizeof(unsigned long)))
  34.         | REGISTER_RESULT_LOCATION(kRegisterD0)
  35.         | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(unsigned long)))
  36.     };
  37.  
  38. //    an icky little struct that makes the world go around
  39.  
  40. #pragma options align=mac68k
  41.  
  42. typedef    struct    JADBProcGlueCode
  43.     {
  44.     UInt16                    jsrLong;
  45.     UniversalProcPtr        ourJADBProc;
  46.     UInt16                    jmpLong;
  47.     UniversalProcPtr        oldJADBProc;
  48.  
  49.     // We want to flush the DR cache after we modify the above fields.  However,
  50.     // there does not seem to be any way to do this from PPC code.  The only
  51.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  52.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  53.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  54.     // > 20 bytes.
  55.  
  56.     UInt32                    padForBlockMove[5];
  57.     }    JADBProcGlueCode;
  58.  
  59. #pragma options align=reset
  60.  
  61. static JADBProcGlueCode*        gMouseJumpIsland;
  62.  
  63. static UInt32 myMouseADBProc(UInt32 adbReInitState);
  64.  
  65. RoutineDescriptor myMouseADBProcRD = BUILD_ROUTINE_DESCRIPTOR(uppJADBProcProcInfo, (ProcPtr) myMouseADBProc);
  66.  
  67. extern    usbMousePBStruct myMousePB;
  68.  
  69. USBHIDRev2DispatchTable TheHIDModuleDispatchTable =
  70. {
  71.     (UInt32)0,
  72.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  73.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  74.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  75.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  76.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  77.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  78.     (USBHIDInstallNotificationProcPtr)USBHIDInstallNotification
  79. };
  80.  
  81. void USBMouseIn(UInt32 refcon, void * theData)
  82. {
  83. #pragma unused (refcon)
  84.  
  85. USBHIDDataPtr    pMouseData;
  86. static UInt16     oldbuttons = 0;
  87. UInt16     changedbuttons = 0;
  88.  
  89. //    DebugStr("\pIn USBMouseIn");
  90.     pMouseData = (USBHIDDataPtr)theData;
  91.     
  92.     if (myMousePB.pCursorDeviceInfo)        // don't call cursor device manager functions without a good cursor device
  93.     {
  94.         // Tell the Cursor Device Manager that we moved
  95.         if ((pMouseData->mouse.XDelta != 0) || (pMouseData->mouse.YDelta !=0))
  96.         {
  97.             CursorDeviceMove(myMousePB.pCursorDeviceInfo, pMouseData->mouse.XDelta, pMouseData->mouse.YDelta);
  98.         }
  99.         
  100.         // Update with the state of the buttons.
  101.         pMouseData->mouse.buttons &= 0x07;
  102.         changedbuttons = oldbuttons ^ pMouseData->mouse.buttons;
  103.         if (changedbuttons)
  104.         {
  105.             CursorDeviceButtons(myMousePB.pCursorDeviceInfo, (short)pMouseData->mouse.buttons);
  106.         }
  107.         oldbuttons = pMouseData->mouse.buttons;
  108.     }
  109. }
  110.  
  111. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  112. {
  113.     USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set interrupt pointer", (UInt32)HIDInterruptFunction);
  114.     myMousePB.interruptRefcon = refcon;            
  115.     
  116.     if (HIDInterruptFunction == USBMouseIn)                // if someone is re-installing the USBMouseIn routine then this is
  117.     {                                                    // an indication that someone earlier requested the interrupt
  118.         myMousePB.pSHIMInterruptRoutine = nil;            // pointer, saved it, and restored it.  When the USBMouseIn
  119.         USBHIDControlDevice(kHIDEnableDemoMode, 0);        // routine is to be used, we've got to re-enable demo mode,
  120.                                                         // otherwise there won't be a cursor device manager entry for us...
  121.     }
  122.     else
  123.     {
  124.         USBHIDControlDevice(kHIDDisableDemoMode, 0);    // disable demo mode
  125.         myMousePB.pSHIMInterruptRoutine = HIDInterruptFunction;
  126.     }
  127.     return noErr;
  128. }
  129.  
  130. OSStatus USBHIDInstallNotification(HIDNotificationProcPtr HIDNotification, UInt32 refcon)
  131. {
  132.     USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set notification proc ptr", (UInt32)HIDNotification);
  133.     myMousePB.notificationRefcon = refcon;            
  134.     
  135.     myMousePB.pNotificationRoutine = HIDNotification;
  136.     return noErr;
  137. }
  138.  
  139. OSStatus USBHIDPollDevice(void)
  140. {
  141.     return kUSBInternalErr;
  142. }
  143.  
  144. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  145. {
  146. #pragma unused (theControlData)
  147.  
  148.     switch (theControlSelector)
  149.     {
  150.         case kHIDRemoveInterruptHandler:
  151.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing interrupt handler!!!", myMousePB.interfaceRef);
  152.             myMousePB.interruptRefcon = nil;
  153.             myMousePB.pSavedInterruptRoutine = nil;
  154.             myMousePB.pSHIMInterruptRoutine = nil;
  155.             if (myMousePB.pCursorDeviceInfo != 0)
  156.             {
  157.                 CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
  158.                 myMousePB.pCursorDeviceInfo = 0;
  159.             }
  160.             break;
  161.             
  162.         case kHIDRemoveNotification:
  163.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing notification!!!", myMousePB.interfaceRef);
  164.             myMousePB.notificationRefcon = nil;
  165.             myMousePB.pNotificationRoutine = NotifyRegisteredHIDUser;
  166.             break;
  167.             
  168.         case kHIDEnableDemoMode:
  169.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Enabled", myMousePB.interfaceRef);
  170.             
  171.             if (myMousePB.pCursorDeviceInfo == 0)
  172.             {
  173.                 myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
  174.                 CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
  175.                 
  176.                 CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
  177.                 
  178.                 CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3);            // should actually be set by reading
  179.                                                                                 // the HID descriptor, but lacking
  180.                                                                                 // a parser, we'll just force it
  181.                                                                                 // this way.
  182.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
  183.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
  184.                 CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
  185.                 CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
  186.             
  187.                 myMousePB.pSavedInterruptRoutine = myMousePB.pSHIMInterruptRoutine;
  188.                 myMousePB.pSHIMInterruptRoutine = USBMouseIn;
  189.             }
  190.             break;
  191.  
  192.         case kHIDDisableDemoMode:
  193.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Disabled", myMousePB.interfaceRef);
  194.             if (myMousePB.pCursorDeviceInfo != 0)
  195.             {
  196.                 CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
  197.                 myMousePB.pCursorDeviceInfo = 0;
  198.             }
  199.             myMousePB.pSHIMInterruptRoutine = myMousePB.pSavedInterruptRoutine;
  200.             break;
  201.  
  202.         default:
  203.             return paramErr;
  204.     }
  205.     return noErr;
  206. }
  207.  
  208.  
  209.  
  210. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  211. {
  212. HIDInterruptProcPtr * pHIDIntProcPtr;
  213. UInt32 * pUnits;
  214. UInt32 * pInterruptRefcon;
  215.  
  216.     switch (theInfoSelector)
  217.     {
  218.         case kHIDGetDeviceUnitsPerInch:
  219.             pUnits = (UInt32*)theInfo;
  220.             *pUnits = (UInt32)(myMousePB.unitsPerInch);
  221.             break;
  222.             
  223.         case kHIDGetInterruptHandler:
  224.             USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Get interrupt pointer", (UInt32)(myMousePB.pSHIMInterruptRoutine));
  225.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;     
  226.             *pHIDIntProcPtr = myMousePB.pSHIMInterruptRoutine;
  227.             break;
  228.  
  229.         case kHIDGetInterruptRefcon:
  230.             pInterruptRefcon = (UInt32 *)theInfo;
  231.             *pInterruptRefcon = myMousePB.interruptRefcon;
  232.             break;
  233.         
  234.         default:
  235.             return paramErr;
  236.     }
  237.     return noErr;
  238. }
  239.  
  240. OSStatus USBHIDEnterPolledMode(void)
  241. {
  242.     return unimpErr;
  243. }
  244.  
  245. OSStatus USBHIDExitPolledMode(void)
  246. {
  247.     return unimpErr;
  248. }
  249.  
  250. void NotifyRegisteredHIDUser(UInt32 refcon, UInt32 reportSize, void * theReport, USBReference theInterfaceRef)
  251. //void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  252. {
  253. #pragma unused (refcon)
  254. #pragma unused (reportSize)
  255. #pragma unused (theInterfaceRef)
  256.  
  257. USBHIDData        theMouseData;
  258. SInt8            myXDelta, myYDelta;
  259. char *             hidReport;
  260.  
  261.     hidReport = (char *)theReport;
  262.     theMouseData.mouse.buttons = (UInt16)hidReport[0];
  263.     
  264.     myXDelta = (SInt8)hidReport[1];
  265.     myYDelta = (SInt8)hidReport[2];  
  266.     
  267.     theMouseData.mouse.XDelta = (SInt16)myXDelta;
  268.     theMouseData.mouse.YDelta = (SInt16)myYDelta;
  269.     if (myMousePB.pSHIMInterruptRoutine)
  270.     {
  271.         (*myMousePB.pSHIMInterruptRoutine)(myMousePB.interruptRefcon, (void *)&theMouseData);
  272.     }
  273. }
  274.  
  275. static UInt32
  276. myMouseADBProc(UInt32 adbReInitState)
  277. {
  278.  
  279.     // adbReInitState = 0, just before the cursor device manager devices are removed.
  280.     // adbReInitState = non-zero, after the devices are removed.  This is when we need to
  281.     // reinsert our device.
  282.  
  283.     if (adbReInitState == 0)
  284.     {
  285.         if (myMousePB.pCursorDeviceInfo != 0)                
  286.         {
  287.             myMousePB.pCursorDeviceInfo = 0;
  288.         }
  289.     }
  290.     else
  291.     {
  292.         if (myMousePB.pSHIMInterruptRoutine == USBMouseIn)  // are we using our cursor device?
  293.         {
  294.             myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
  295.             CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
  296.             
  297.             CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
  298.             
  299.             CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3);            // should actually be set by reading
  300.                                                                             // the HID descriptor, but lacking
  301.                                                                             // a parser, we'll just force it
  302.                                                                             // this way.
  303.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
  304.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
  305.             CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
  306.             CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
  307.         }
  308.     }
  309.  
  310.     return(adbReInitState);
  311. }
  312.  
  313.  
  314. void ChainJADBProc(void)
  315. {
  316.     JADBProcGlueCode            stackedBasedVersion;
  317.  
  318.     // Hook ourselves into JADBProc to be notified whenever ADBReInit gets called.  As a
  319.     // result of ADBReInit(), any CursorDevice records are deleted.  So, we'll hook ourselves
  320.     // into JADBProc, and recreate our CursorDevice record whenever ADBReInit has completed.
  321.  
  322.  
  323.     if ((gMouseJumpIsland = (JADBProcGlueCode *) NewPtrSysClear(sizeof(JADBProcGlueCode))) == nil)
  324.     {
  325.         return;  // just bail if we can't allocate any memory
  326.     }
  327.  
  328.     stackedBasedVersion.jsrLong = 0x4EB9;
  329.     stackedBasedVersion.ourJADBProc = &myMouseADBProcRD;
  330.     stackedBasedVersion.jmpLong = 0x4EF9;
  331.     stackedBasedVersion.oldJADBProc = LMGetJADBProc();
  332.  
  333.     // We want to flush the DR cache after we modify the above fields.  However,
  334.     // there does not seem to be any way to do this from PPC code.  The only
  335.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  336.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  337.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  338.     // > 20 bytes.
  339.  
  340.     BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
  341.  
  342.     LMSetJADBProc((UniversalProcPtr) gMouseJumpIsland);
  343. }
  344.  
  345. void UnchainJADBProc(void)
  346. {
  347.     JADBProcGlueCode        stackedBasedVersion;
  348.  
  349.     // We cannot totally remove ourselves from the ADBReinit chain.  Since someone might have patched
  350.     // themselves into the JADBProc chain after us, we need to leave a small jump island pointing
  351.     // to the person before us in the chain.
  352.  
  353.     // We want to flush the DR cache after we modify the above fields.  However,
  354.     // there does not seem to be any way to do this from PPC code.  The only
  355.     // real way to do this, is to copy this data structure onto itself.  BlockMove
  356.     // will flush the DR cache then.  Of course, BlockMove will not flush the DR cache
  357.     // for BlockMove's of less than 20 bytes.  We need to pad our data structure out to be
  358.     // > 20 bytes.
  359.  
  360.     BlockMove(gMouseJumpIsland, &stackedBasedVersion, sizeof(JADBProcGlueCode));
  361.  
  362.     stackedBasedVersion.jsrLong = 0x2048;
  363.     stackedBasedVersion.ourJADBProc = (UniversalProcPtr) 0x20482048;
  364.  
  365.     BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
  366. }